#include <iostream>
#include <functional>
#include <memory>
#include <vector>
#include <unistd.h>
#include <unordered_map>

using TaskFunc = std::function<void()>;
using ReleaseFunc = std::function<void()>;

class TimerTask
{
private:
    u_int64_t _id ; //定时器任务id
    u_int32_t _timeout ; // 超时时间
    bool _canceled; //false表示不取消，true表示取消
    TaskFunc _taskcb ; //要执行的定时任务
    ReleaseFunc _release; //删除定时器对象信息
public:
    TimerTask(u_int64_t id , u_int32_t delay , const TaskFunc &cb ):
        _id(id) , _timeout(delay) , _taskcb(cb){}
    ~TimerTask()
    {
        if(_canceled == false) _taskcb();
        _release();
    }
    void Cancel() {_canceled = true;}
    void SetRelease(const ReleaseFunc& cb) {_release = cb;};
    u_int32_t DelayTime() {return _timeout;}
};
class TimeWheel
{
private:
    using PtrTask = std::shared_ptr<TimerTask>;
    using WeakTask = std::weak_ptr<TimerTask>;
    int _tick ; // 秒针，指向哪里就释放哪里，执行对应的任务
    int _capacity ; //表盘最大数量， 最大延迟时间
    std::vector<std::vector<PtrTask>> _wheel;
    std::unordered_map<u_int64_t , WeakTask> _timers;
private:
    void RemoveTimer(u_int64_t id)
    {
        auto it = _timers.find(id);
        if(it != _timers.end())
        {
            _timers.erase(it);
        }
    }
public:
    TimeWheel():_capacity(60) , _tick(0) , _wheel(_capacity){}
    void TimerAdd(u_int64_t id , u_int32_t delay , const TaskFunc& cb)
    {  
        PtrTask pt(new TimerTask(id , delay , cb));
        pt->SetRelease(std::bind(&TimeWheel::RemoveTimer , this , id));
        int pos = (_tick + delay) % _capacity;
        _wheel[pos].push_back(pt);
        _timers[id] = WeakTask(pt);
    }

    void TimerRefresh(u_int64_t id)
    {
        auto it = _timers.find(id);
        if(it == _timers.end())
        {
            return ;
        }
        PtrTask pt = it->second.lock(); // 获取对象对应的shared_ptr
        int delay = pt->DelayTime();
        int pos = (_tick + delay) % _capacity;
        _wheel[pos].push_back(pt);
    }
    void TimerCancel(u_int64_t id)
    {
        auto it = _timers.find(id);
        if(it == _timers.end())
        {
            return ;
        }
        PtrTask pt = it->second.lock();
        if(pt) pt->Cancel();
    }
    void RunTimerTask()
    {
        _tick = (_tick + 1)%_capacity;
        _wheel[_tick].clear(); //释放对应的shared_ptr
    }
};

class Test {
    public:
        Test() {std::cout << "构造" << std::endl;}
        ~Test() {std::cout << "析构" << std::endl;}
};

void DelTest(Test *t) {
    delete t;
}

int main()
{
    TimeWheel tw;

    Test *t = new Test();

    tw.TimerAdd(888, 5, std::bind(DelTest, t));

    for(int i = 0; i < 5; i++) {
        sleep(1);
        tw.TimerRefresh(888);//刷新定时任务
        tw.RunTimerTask();//向后移动秒针
        std::cout << "刷新了一下定时任务，重新需要5s中后才会销毁\n";
    }
    // tw.TimerCancel(888);
    while(1) {
        sleep(1);
        std::cout << "-------------------\n";
        tw.RunTimerTask();//向后移动秒针
    }
    return 0;
}